<template>
  <view class="sso-container">
    <web-view
        v-if="webviewUrl"
        :src="webviewUrl"
    ></web-view>
    <view v-else class="loading">
      <text>正在加载统一认证页面...</text>
    </view>
    <view v-if="showLoginResult" class="login-result-overlay">
      <view class="result-box" :class="{'success': loginSuccess, 'error': !loginSuccess}">
        <uni-icons
            :type="loginSuccess ? 'checkbox-filled' : 'clear'"
            :color="loginSuccess ? '#52c41a' : '#ff4d4f'"
            size="40"
        ></uni-icons>
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref, onUnmounted } from 'vue'
import { onLoad } from '@dcloudio/uni-app'

import store from '@/store'
import loginApi from '@/api/auth/login-api'
import userCenterApi from '@/api/sys/user-center-api'
import dictApi from '@/api/dev/dict-api'

const SSO_HOST = "https://sso.scnu.edu.cn/AccountService"
const REDIRECT_URL = "https://soulmeet.scnu.edu.cn/WeChatCallback"
const CLIENT_ID = "678385ffaec2c4b1a632e755e4a2a38b"
const WECHAT_APPID = "wx12f95b7ff470609e"
const WECHAT_SSO_Login = SSO_HOST + "/openapi/wechat_applet.html"

const webviewUrl = ref('')
const loginSuccess = ref(false)
const showLoginResult = ref(false)

const pollingTimer = ref(null)
const pollingCode = ref('')
const maxPollingAttempts = 60
const currentPollingAttempts = ref(0)

// 初始化 SSO 登录
const initSSOLogin = (wxCode) => {
  const encodedWxCode = encodeURIComponent(wxCode)
  const redirectUriWithCode = `${REDIRECT_URL}?unicode=${encodedWxCode}`

  const queryParams = {
    client_id: CLIENT_ID,
    response_type: 'code',
    redirect_uri: redirectUriWithCode,
    code: wxCode,
    applet_id: WECHAT_APPID,
    t: Date.now()
  }

  const queryString = buildQueryString(queryParams)
  webviewUrl.value = `${WECHAT_SSO_Login}?${queryString}`

  startPolling(wxCode)
}

const buildQueryString = (params) => {
  return Object.keys(params)
      .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
      .join('&')
}

const startPolling = (code) => {
  pollingCode.value = code
  currentPollingAttempts.value = 0

  // console.log('开始轮询Redis，code:', code)

  pollingTimer.value = setInterval( () => {
    try {
      currentPollingAttempts.value++

      if (currentPollingAttempts.value > maxPollingAttempts) {
        stopPolling()
        handlePollingTimeout()
        return
      }
      // console.log(`第${currentPollingAttempts.value}次轮询...`)

      loginApi
          .getUniLoginCode({
            uniappLoginCode: pollingCode.value
          }, { showLoading: false })
          .then((res) => {
            if (res) {
              // console.log('轮询成功，获取到SSOCode:', res)
              stopPolling()
              handlePollingSuccess(res)
            }
          })
    } catch (error) {
      // console.log('轮询请求失败:', error) // 继续轮询，不中断
    }
  }, 5000)
}

const stopPolling = () => {
  if (pollingTimer.value) {
    clearInterval(pollingTimer.value)
    pollingTimer.value = null
    // console.log('轮询已停止')
  }
}

// 轮询成功处理
const handlePollingSuccess = (code) => {
  loginApi
    .SCNUSSOWeChatLogin({
      code: code
    })
    .then((res) => {
      // 缓存token
      store.commit('SET_token', res)

      // 执行登录后操作
      Promise.all([
        store.dispatch('GetUserLoginMenu'),
        store.dispatch('GetUserInfo'),
        store.dispatch('GetDictTypeTreeData')
      ]).then(() => {
        // 跳转到首页
        uni.$snowy.tab.reLaunch('/pages/home/index')
      }).catch(err => {
        console.error('登录后操作失败:', err)
      })
    })
    .catch(err => {
      console.error('SSO登录失败:', err)
      showLoginResult.value = true
      loginSuccess.value = false
    })
}

// 轮询超时处理
const handlePollingTimeout = () => {
  console.log('轮询超时')
  uni.showModal({
    title: '提示',
    content: '登录超时，请重新登录。',
    showCancel: false,
    success: function (res) {
      if (res.confirm) {
        uni.$snowy.tab.reLaunch('/pages/auth/login')
      }
    }
  })
}

onLoad((options) => {
  showLoginResult.value = false;

  const wxCode = options.wxCode || ''
  if (!wxCode) {
    showLoginResult.value = true
    loginSuccess.value = false
    return
  }

  initSSOLogin(wxCode)
})

onUnmounted(() => {
  showLoginResult.value = false
  stopPolling()
})
</script>

<style lang="scss" scoped>
.sso-container {
  width: 100%;
  height: 100vh;
  background: #f5f7fa;
  position: relative;
}

.login-result-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;

  .result-box {
    background: #fff;
    border-radius: 16rpx;
    padding: 40rpx;
    width: 80%;
    max-width: 500rpx;
    text-align: center;
    box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1);

    &.success {
      border-top: 8rpx solid #52c41a;
    }

    &.error {
      border-top: 8rpx solid #ff4d4f;
    }

    .result-text {
      display: block;
      margin: 20rpx 0 30rpx;
      font-size: 32rpx;
      color: #333;
    }

    .close-btn {
      background: #1890ff;
      color: #fff;
      border: none;
      border-radius: 8rpx;
      padding: 12rpx 24rpx;
      font-size: 28rpx;
    }
  }
}

.loading {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100vh;
  font-size: 32rpx;
  color: #606266;

  &:before {
    content: "";
    display: block;
    width: 120rpx;
    height: 120rpx;
    margin-bottom: 30rpx;
    border: 8rpx solid #e4e7ed;
    border-top-color: #409eff;
    border-radius: 50%;
    animation: spin 1s linear infinite;
  }
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
</style>